package com.hongyi.websocket.config;

import cn.hutool.core.util.StrUtil;
import com.hongyi.websocket.config.properties.WebSocketProperties;
import com.hongyi.websocket.handler.LyWebSocketHandler;
import com.hongyi.websocket.interceptor.WebSocketInterceptor;
import com.hongyi.websocket.listener.WebSocketTopicListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.server.HandshakeInterceptor;

/**
 * WebSocket 配置
 *
 * @author zendwang
 */
@Slf4j
@Configuration
@EnableConfigurationProperties(WebSocketProperties.class)//自动绑定与WebSocketProperties类中字段匹配的外部配置属性
@ConditionalOnProperty(value = "websocket.enabled", havingValue = "true")//当配置类中websocket.enabled的属性值为true时，Spring才会加载这个配置类
@EnableWebSocket//启用Spring WebSocket支持。通过实现WebSocketConfigurer接口来配置WebSocket端点
public class WebSocketConfig {

    public WebSocketConfig() {
        log.info("加载WebSocket配置类");
    }

    /**
     * 自定义WebSocketConfigurer类型的bean
     *
     * <p>用于配置WebSocket处理器、拦截器以及允许的源</p>
     * @param handshakeInterceptor       握手拦截器
     * @param webSocketHandler           WebSocket处理器
     * @param webSocketProperties        WebSocket属性
     */
    @Bean
    public WebSocketConfigurer webSocketConfigurer(HandshakeInterceptor handshakeInterceptor,
                                                   WebSocketHandler webSocketHandler,
                                                   WebSocketProperties webSocketProperties) {
        //如果WebSocketProperties中的路径未设置，则默认设置为/websocket
        if (StrUtil.isBlank(webSocketProperties.getPath())) {
            webSocketProperties.setPath("/websocket");
        }
        //如果WebSocketProperties中的允许来源未设置，则默认设置为*，表示允许所有来源
        if (StrUtil.isBlank(webSocketProperties.getAllowedOrigins())) {
            webSocketProperties.setAllowedOrigins("*");
        }
        //webSocketHandler映射到指定的路径，并添加了handshakeInterceptor作为握手拦截器，设置了允许的跨域来源
        return registry -> registry
            .addHandler(webSocketHandler, webSocketProperties.getPath())
            .addInterceptors(handshakeInterceptor)
            .setAllowedOrigins(webSocketProperties.getAllowedOrigins());
    }

    /**
     * 创建并返回一个HandshakeInterceptor实例
     *
     * <p>这里是WebSocketInterceptor，它可以在WebSocket连接建立之前执行某些逻辑</p>
     */
    @Bean
    public HandshakeInterceptor handshakeInterceptor() {
        return new WebSocketInterceptor();
    }

    /**
     * 创建并返回一个WebSocketHandler实例
     *
     * <p>这里是LyWebSocketHandler，它负责处理WebSocket消息的接收和发送</p>
     */
    @Bean
    public WebSocketHandler webSocketHandler() {
        return new LyWebSocketHandler();
    }

    /**
     * 创建并返回一个WebSocketTopicListener实例
     *
     * <p>这里是WebSocketTopicListener，用来监听某些WebSocket主题的变化或者处理订阅相关的逻辑</p>
     */
    @Bean
    public WebSocketTopicListener topicListener() {
        return new WebSocketTopicListener();
    }
}
